
/********************************************************************************************************
*
* File                : CC1101.C
*
*********************************************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "common.h"
#include "delay.h"
#include "spi.h"
#include "cc1101.h"
#include "msg.h"



/*******************************************************************************
* Typedef
*******************************************************************************/

#define DEBUG_CC1101



#define _CS_PORT_       GPIOA
#define _CS_PIN_          GPIO_Pin_4

#define _GDIO0_PORT_       GPIOB
#define _GDIO0_PIN_          GPIO_Pin_1

#define _GDIO2_PORT_       GPIOB
#define _GDIO2_PIN_          GPIO_Pin_0

#define _MISO_PORT_       GPIOA
#define _MISO_PIN_          GPIO_Pin_6



typedef struct
{
  UINT8   addr;
  UINT8   data;
}registerSetting_t;


typedef UINT8 rfStatus_t; 


/*******************************************************************************
* Macro
*******************************************************************************/

#define _select()           GPIO_ResetBits(_CS_PORT_,_CS_PIN_)
#define _deselect()       GPIO_SetBits(_CS_PORT_,_CS_PIN_)




/*******************************************************************************
* Global Variable
*******************************************************************************/

/* Radio configurations exported from SmartRF Studio*/
 
/*
 * Deviation = 5.157471 
 * Base frequency = 433.999969 
 * Carrier frequency = 433.999969 
 * Channel number = 0 
 * Carrier frequency = 433.999969 
 * Modulated = true 
 * Modulation format = GFSK 
 * Manchester enable = false 
 * Sync word qualifier mode = 30/32 sync word bits detected 
 * Preamble count = 4 
 * Channel spacing = 199.951172 
 * Carrier frequency = 433.999969 
 * Data rate = 1.19948 
 * RX filter BW = 58.035714 
 * Data format = Normal mode 
 * Length config = Variable packet length mode. Packet length configured by the first byte after sync word 
 * CRC enable = true 
 * Packet length = 255 
 * Device address = 0 
 * Address config = No address check 
 * CRC autoflush = false 
 * PA ramping = false 
 * TX power = -10 
 */
static const registerSetting_t lowDataRateRfSettings[] = {
    {CC1101_IOCFG2    ,0x29},  /* IOCFG2        GDO2 Output Pin Configuration                  */
    {CC1101_IOCFG1    ,0x2E},  /* IOCFG1        GDO1 Output Pin Configuration                  */
    {CC1101_IOCFG0    ,0x06},  /* IOCFG0        GDO0 Output Pin Configuration                  */
    {CC1101_FIFOTHR   ,0x07},  /* FIFOTHR       RX FIFO and TX FIFO Thresholds                 */
    {CC1101_SYNC1     ,0xD3},  /* SYNC1         Sync Word, High Byte                           */
    {CC1101_SYNC0     ,0x91},  /* SYNC0         Sync Word, Low Byte                            */
    {CC1101_PKTLEN    ,0xFF},  /* PKTLEN        Packet Length                                  */
    {CC1101_PKTCTRL1  ,0x04},  /* PKTCTRL1      Packet Automation Control                      */
    {CC1101_PKTCTRL0  ,0x05},  /* PKTCTRL0      Packet Automation Control                      */
    {CC1101_ADDR      ,0x00},  /* ADDR          Device Address                                 */
    {CC1101_CHANNR    ,0x00},  /* CHANNR        Channel Number                                 */
    {CC1101_FSCTRL1   ,0x06},  /* FSCTRL1       Frequency Synthesizer Control                  */
    {CC1101_FSCTRL0   ,0x00},  /* FSCTRL0       Frequency Synthesizer Control                  */
    {CC1101_FREQ2     ,0x10},  /* FREQ2         Frequency Control Word, High Byte              */
    {CC1101_FREQ1     ,0xB1},  /* FREQ1         Frequency Control Word, Middle Byte            */
    {CC1101_FREQ0     ,0x3B},  /* FREQ0         Frequency Control Word, Low Byte               */
    {CC1101_MDMCFG4   ,0xF5},  /* MDMCFG4       Modem Configuration                            */
    {CC1101_MDMCFG3   ,0x83},  /* MDMCFG3       Modem Configuration                            */
    {CC1101_MDMCFG2   ,0x13},  /* MDMCFG2       Modem Configuration                            */
    {CC1101_MDMCFG1   ,0x22},  /* MDMCFG1       Modem Configuration                            */
    {CC1101_MDMCFG0   ,0xF8},  /* MDMCFG0       Modem Configuration                            */
    {CC1101_DEVIATN   ,0x15},  /* DEVIATN       Modem Deviation Setting                        */
    {CC1101_MCSM2     ,0x07},  /* MCSM2         Main Radio Control State Machine Configuration */
    {CC1101_MCSM1     ,0x30},  /* MCSM1         Main Radio Control State Machine Configuration */
    {CC1101_MCSM0     ,0x18},  /* MCSM0         Main Radio Control State Machine Configuration */
    {CC1101_FOCCFG    ,0x16},  /* FOCCFG        Frequency Offset Compensation Configuration    */
    {CC1101_BSCFG     ,0x6C},  /* BSCFG         Bit Synchronization Configuration              */
    {CC1101_AGCCTRL2  ,0x03},  /* AGCCTRL2      AGC Control                                    */
    {CC1101_AGCCTRL1  ,0x40},  /* AGCCTRL1      AGC Control                                    */
    {CC1101_AGCCTRL0  ,0x91},  /* AGCCTRL0      AGC Control                                    */
    {CC1101_WOREVT1   ,0x87},  /* WOREVT1       High Byte Event0 Timeout                       */
    {CC1101_WOREVT0   ,0x6B},  /* WOREVT0       Low Byte Event0 Timeout                        */
    {CC1101_WORCTRL   ,0xFB},  /* WORCTRL       Wake On Radio Control                          */
    {CC1101_FREND1    ,0x56},  /* FREND1        Front End RX Configuration                     */
    {CC1101_FREND0    ,0x10},  /* FREND0        Front End TX Configuration                     */
    {CC1101_FSCAL3    ,0xE9},  /* FSCAL3        Frequency Synthesizer Calibration              */
    {CC1101_FSCAL2    ,0x2A},  /* FSCAL2        Frequency Synthesizer Calibration              */
    {CC1101_FSCAL1    ,0x00},  /* FSCAL1        Frequency Synthesizer Calibration              */
    {CC1101_FSCAL0    ,0x1F},  /* FSCAL0        Frequency Synthesizer Calibration              */
    {CC1101_RCCTRL1   ,0x41},  /* RCCTRL1       RC Oscillator Configuration                    */
    {CC1101_RCCTRL0   ,0x00},  /* RCCTRL0       RC Oscillator Configuration                    */
    {CC1101_FSTEST    ,0x59},  /* FSTEST        Frequency Synthesizer Calibration Control      */
    {CC1101_PTEST     ,0x7F},  /* PTEST         Production Test                                */
    {CC1101_AGCTEST   ,0x3F},  /* AGCTEST       AGC Test                                       */
    {CC1101_TEST2     ,0x81},  /* TEST2         Various Test Settings                          */
    {CC1101_TEST1     ,0x35},  /* TEST1         Various Test Settings                          */
    {CC1101_TEST0     ,0x09}  /* TEST0         Various Test Settings                           */
}; 



static rfStatus_t cc1101RadioTxRx;






/*******************************************************************************
* Functions
*******************************************************************************/
void CC1101_dbg_read_register(void);







/*-----------------------------------------------------------------------------
  Function Name  : CC1101_ReadWrite_BurstSingle
------------------------------------------------------------------------------*/

static void CC1101_ReadWrite_BurstSingle(UINT8 addr,UINT8 *pData,UINT16 len)
{ 
	UINT16 i;
	/* Communicate len number of bytes: if RX - the procedure sends 0x00 to push bytes from slave*/
  if(addr&RADIO_READ_ACCESS)
  {
    if(addr&RADIO_BURST_ACCESS)
    {
      for (i = 0; i < len; i++)
      {
          *pData = SPI_read_write(_SPI1_, 0x00);
          pData++;
      }
    }
    else
    {
        *pData = SPI_read_write(_SPI1_, 0x00);
    }
  }
  else
  {
    if(addr&RADIO_BURST_ACCESS)
    {
      /* Communicate len number of bytes: if TX - the procedure doesn't overwrite pData */
      for (i = 0; i < len; i++)
      {
        SPI_read_write(_SPI1_, *pData);
        pData++;
      }    
    }
    else
    {
        SPI_read_write(_SPI1_, *pData);
    }
  }
  return;
}






/*-----------------------------------------------------------------------------
  Function Name  : CC1101_8Bit_Reg_Access
------------------------------------------------------------------------------*/
rfStatus_t CC1101_8Bit_Reg_Access(UINT8 accessType, UINT8 addrByte, UINT8 *pData, UINT16 len)
{
  UINT8 readValue;
    
  /* Pull CS_N low and wait for SO to go low before communication starts */
  _select();
  while(GPIO_ReadOutputDataBit(_MISO_PORT_, _MISO_PIN_));


  readValue = SPI_read_write(_SPI1_,accessType|addrByte );

#if 0
  /* send register address byte */
  TRXEM_SPI_TX(accessType|addrByte);
  TRXEM_SPI_WAIT_DONE();
  /* Storing chip status */
  readValue = TRXEM_SPI_RX(); 
#endif

  
  CC1101_ReadWrite_BurstSingle(accessType|addrByte,pData,len);

  
  _deselect();
  /* return the status byte value */
  return(readValue);
}



/*-----------------------------------------------------------------------------
  Function Name  : CC1101_Cmd_Strobe
------------------------------------------------------------------------------*/
rfStatus_t CC1101_Cmd_Strobe(UINT8 cmd)
{
    UINT8 rc;
    _select();
    while(GPIO_ReadOutputDataBit(_MISO_PORT_, _MISO_PIN_));

    
    rc = SPI_read_write(_SPI1_,cmd);
    
    _deselect();
    return(rc);
}







/*-----------------------------------------------------------------------------
  Function Name  : cc1101SpiWriteReg
------------------------------------------------------------------------------*/

rfStatus_t CC1101_Spi_Write_Reg(UINT8 addr, UINT8 *pData, UINT8 len)
{
  UINT8 rc;
  rc = CC1101_8Bit_Reg_Access((RADIO_BURST_ACCESS|RADIO_WRITE_ACCESS),addr, pData, len);
  return (rc);
}


/*-----------------------------------------------------------------------------
  Function Name  : cc1101SpiWriteReg
------------------------------------------------------------------------------*/
rfStatus_t CC1101_Spi_Read_Reg(UINT8 addr, UINT8 *pData, UINT8 len)
{
  UINT8 rc;
  rc = CC1101_8Bit_Reg_Access((RADIO_BURST_ACCESS|RADIO_READ_ACCESS), addr, pData, len);
  return (rc);
}  









/*-----------------------------------------------------------------------------
  Function Name  : CC1101_cs
------------------------------------------------------------------------------*/
void CC1101_IO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;


    /* Chip Selector */
    GPIO_InitStructure.GPIO_Pin = _CS_PIN_;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(_CS_PORT_, &GPIO_InitStructure);



    /* CC1101 GDO0 */
    GPIO_InitStructure.GPIO_Pin = _GDIO0_PIN_;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(_GDIO0_PORT_, &GPIO_InitStructure);


    /* CC1101 GDO2 */
    GPIO_InitStructure.GPIO_Pin = _GDIO2_PIN_;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(_GDIO2_PORT_, &GPIO_InitStructure);

    
}



/*-----------------------------------------------------------------------------
  Function Name  : CC1101_Register_Init
------------------------------------------------------------------------------*/
void CC1101_Register_Init(void)
{
    UINT8 data;

    for(UINT16 i = 0; i < (sizeof lowDataRateRfSettings/sizeof(registerSetting_t));i++)
    {
      data = lowDataRateRfSettings[i].data;
      CC1101_Spi_Write_Reg(lowDataRateRfSettings[i].addr,&data,1);
    }

}



/*-----------------------------------------------------------------------------
  Function Name  : CC1101_Register_Init
------------------------------------------------------------------------------*/
void CC1101_Rx_Idle(void)
{
  /* Disable pin interrupt */
  //trxDisableInt();
  /* Strobe IDLE */
  CC1101_Cmd_Strobe(CC1101_SIDLE); 
  /* Wait until chip is in IDLE */
  while((CC1101_Cmd_Strobe(CC1101_SNOP) & 0xF0));
  /* Flush the Receive FIFO */
  CC1101_Cmd_Strobe(CC1101_SFRX);

  /* Clear pin interrupt flag */
 // trxClearIntFlag();
  return;
}




/*-----------------------------------------------------------------------------
  Function Name  : CC1101_init
------------------------------------------------------------------------------*/
void CC1101_Init(void)
{
    SPI1_Init();
    CC1101_IO_Init();

    /* Log that radio is in IDLE state */
    CC1101_Rx_Idle();
    cc1101RadioTxRx = CC1101_STATE_IDLE;



//    CC1101_Register_Init();
    CC1101_Register_Init();

#ifdef DEBUG_CC1101
    CC1101_dbg_read_register();
#endif


}















/*-----------------------------------------------------------------------------
  Function Name  : CC1101_dbg_read_register
------------------------------------------------------------------------------*/
void CC1101_dbg_read_register(void)
{

    UINT8 data;

    BMSG("\r\n =================================================================",0);
    
    for(UINT16 i = 0; i < (sizeof lowDataRateRfSettings/sizeof(registerSetting_t));i++)
    {
        CC1101_Spi_Read_Reg(lowDataRateRfSettings[i].addr,&data,1);

        if((lowDataRateRfSettings[i].addr & 0x0F) == 0x00)
        {
            BMSG("\r\n[%02X] ",lowDataRateRfSettings[i].addr);
        }

        BMSG("%02X, ",data);
    }

    MSG("",0);
    
}




